"""测试工具模块

提供测试中使用的通用工具函数
包括响应验证、数据生成等功能
"""

from typing import Dict, Any, List
import json
import time
from datetime import datetime, timedelta
from typing import Optional
from unittest.mock import Mock, patch
import pytest


def assert_response_structure(response_data: Dict[str, Any], expected_fields: List[str]) -> bool:
    """验证响应数据结构是否包含预期字段"""
    for field in expected_fields:
        if field not in response_data:
            return False
    return True


class TestDataGenerator:
    """测试数据生成"""
    
    @staticmethod
    def generate_session_data(id: str = None, **kwargs) -> Dict[str, Any]:
        """生成会话测试数据"""
        if id is None:
            id = f"test_session_{int(time.time())}"
        
        default_data = {
            "id": id,
            "room_id": f"room_{id}",
            "user_id": "test_user",
            "start_time": datetime.now().isoformat(),
            "end_time": None,
            "total_seconds": 0
        }
        default_data.update(kwargs)
        return default_data
    
    @staticmethod
    def generate_eeg_data(id: str = None, **kwargs) -> Dict[str, Any]:
        """生成脑波数据"""
        if id is None:
            id = f"test_session_{int(time.time())}"
        
        # 生成模拟的脑波数“        wave_frames = [float(i * 0.1) for i in range(100)]
        filtered_frames = [float(i * 0.05) for i in range(100)]
        
        default_data = {
            "id": id,
            "eeg_wave_data": {
                "frame_rate": 250,
                "wave": {"frames": wave_frames},
                "filtered": {"frames": filtered_frames}
            },
            "delta_data": {
                "frame_rate": 250,
                "wave": {"frames": wave_frames[:50]},
                "filtered": {"frames": filtered_frames[:50]}
            },
            "theta_data": {
                "frame_rate": 250,
                "wave": {"frames": wave_frames[25:75]},
                "filtered": {"frames": filtered_frames[25:75]}
            },
            "low_alpha_data": {
                "frame_rate": 250,
                "wave": {"frames": wave_frames[10:60]},
                "filtered": {"frames": filtered_frames[10:60]}
            },
            "high_alpha_data": {
                "frame_rate": 250,
                "wave": {"frames": wave_frames[20:70]},
                "filtered": {"frames": filtered_frames[20:70]}
            },
            "low_beta_data": {
                "frame_rate": 250,
                "wave": {"frames": wave_frames[30:80]},
                "filtered": {"frames": filtered_frames[30:80]}
            },
            "high_beta_data": {
                "frame_rate": 250,
                "wave": {"frames": wave_frames[40:90]},
                "filtered": {"frames": filtered_frames[40:90]}
            },
            "gamma_data": {
                "frame_rate": 250,
                "wave": {"frames": wave_frames[50:100]},
                "filtered": {"frames": filtered_frames[50:100]}
            }
        }
        default_data.update(kwargs)
        return default_data
    
    @staticmethod
    def generate_analysis_data(id: str = None, **kwargs) -> Dict[str, Any]:
        """生成分析数据"""
        if id is None:
            id = f"test_session_{int(time.time())}"
        
        default_data = {
            "id": id,
            "analysis_type": "sleep_monitoring",
            "result": {
                "sleep_stage": "deep_sleep",
                "quality_score": 85.5,
                "duration_minutes": 120,
                "efficiency": 0.92
            },
            "created_at": datetime.now().isoformat()
        }
        default_data.update(kwargs)
        return default_data


class TestAssertions:
    """测试断言辅助"""
    
    @staticmethod
    def assert_response_structure(response_data: Dict[str, Any], expected_keys: List[str]):
        """断言响应数据结构"""
        for key in expected_keys:
            assert key in response_data, f"响应中缺少必需的键: {key}"
    
    @staticmethod
    def assert_session_data(session_data: Dict[str, Any]):
        """断言会话数据结构"""
        required_keys = ["id", "room_id", "user_id", "start_time"]
        TestAssertions.assert_response_structure(session_data, required_keys)
        
        assert isinstance(session_data["id"], str)
        assert isinstance(session_data["room_id"], str)
        assert isinstance(session_data["user_id"], str)
    
    @staticmethod
    def assert_eeg_data_structure(eeg_data: Dict[str, Any]):
        """断言脑波数据结构"""
        required_keys = ["id", "eeg_wave_data"]
        TestAssertions.assert_response_structure(eeg_data, required_keys)
        
        # 检查脑波数据结“        wave_data = eeg_data["eeg_wave_data"]
        assert "frame_rate" in wave_data
        assert "wave" in wave_data
        assert "filtered" in wave_data
        assert "frames" in wave_data["wave"]
        assert "frames" in wave_data["filtered"]
        assert isinstance(wave_data["frame_rate"], (int, float))
        assert isinstance(wave_data["wave"]["frames"], list)
        assert isinstance(wave_data["filtered"]["frames"], list)
    
    @staticmethod
    def assert_analysis_result(analysis_data: Dict[str, Any]):
        """断言分析结果结构"""
        required_keys = ["id", "analysis_type", "result"]
        TestAssertions.assert_response_structure(analysis_data, required_keys)
        
        assert isinstance(analysis_data["id"], str)
        assert isinstance(analysis_data["analysis_type"], str)
        assert isinstance(analysis_data["result"], dict)


class MockServices:
    """模拟服务"""
    
    @staticmethod
    def mock_database_session():
        """模拟数据库会"""
        mock_session = Mock()
        mock_session.add = Mock()
        mock_session.commit = Mock()
        mock_session.rollback = Mock()
        mock_session.close = Mock()
        mock_session.query = Mock()
        return mock_session
    
    @staticmethod
    def mock_eeg_service():
        """模拟脑波服务"""
        mock_service = Mock()
        mock_service.start_collection = Mock(return_value={"status": "started"})
        mock_service.stop_collection = Mock(return_value={"status": "stopped"})
        mock_service.get_status = Mock(return_value={"is_active": True})
        mock_service.get_data = Mock(return_value=TestDataGenerator.generate_eeg_data())
        return mock_service
    
    @staticmethod
    def mock_analysis_service():
        """模拟分析服务"""
        mock_service = Mock()
        mock_service.analyze_session = Mock(return_value=TestDataGenerator.generate_analysis_data())
        mock_service.get_history = Mock(return_value={"history": [], "total": 0})
        return mock_service


import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from app.config import settings

def timing_test(max_duration: float = settings.test_max_duration):
    """测试执行时间装饰"""
    def decorator(func):
        def wrapper(*args, **kwargs):
            start_time = time.time()
            result = func(*args, **kwargs)
            end_time = time.time()
            duration = end_time - start_time
            assert duration <= max_duration, f"测试执行时间过长: {duration:.2f}s > {max_duration}s"
            return result
        return wrapper
    return decorator


def retry_on_failure(max_retries: int = settings.test_max_retries, delay: float = settings.test_retry_delay):
    """失败重试装饰"""
    def decorator(func):
        def wrapper(*args, **kwargs):
            last_exception = None
            for attempt in range(max_retries):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    last_exception = e
                    if attempt < max_retries - 1:
                        time.sleep(delay)
                    continue
            raise last_exception
        return wrapper
    return decorator


class TestEnvironment:
    """测试环境管理"""
    
    @staticmethod
    def setup_test_database():
        """设置测试数据"""
        # 这里应该设置测试数据库连“        pass
    
    @staticmethod
    def cleanup_test_database():
        """清理测试数据"""
        # 这里应该清理测试数据
        pass
    
    @staticmethod
    def setup_test_config():
        """设置测试配置"""
        test_config = {
            "DATABASE_URL": "sqlite:///test.db",
            "TESTING": True,
            "DEBUG": True
        }
        return test_config


def validate_json_schema(data: Dict[str, Any], schema: Dict[str, Any]) -> bool:
    """验证JSON数据结构"""
    try:
        # 这里可以使用jsonschema库进行更严格的验“        # 目前使用简单的键检“        for key, expected_type in schema.items():
        if key not in data:
            return False
        if not isinstance(data[key], expected_type):
            return False
        return True
    except Exception:
        return False


def create_test_client():
    """创建测试客户"""
    from fastapi.testclient import TestClient
    from main import app
    return TestClient(app)


TEST_SESSION_SCHEMA = {
    "id": str,
    "room_id": str,
    "user_id": str,
    "start_time": str
}

TEST_EEG_SCHEMA = {
    "id": str,
    "eeg_wave_data": dict
}

TEST_ANALYSIS_SCHEMA = {
    "id": str,
    "analysis_type": str,
    "result": dict
}
